package com.ym521.myktx.encryption

import android.util.Log
import com.ym521.myktx.utils.Base64
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec


/**
 *@author Ym
 *E-mail: 2435970206@qq.com
 *createTime:2024/5/4
 *explain:
 *  AES 加密相关
 */
object AES {
    private const val ALGORITHM = "AES"

    /**
     * ECB模式不是最安全的模式
     */
    object ECB {
        private const val TRANSFORMATION = "AES/ECB/PKCS5Padding"

        /**
         * 加密
         * @param content 需要加密的内容
         * @param key 密钥应该是16（AES-128）、24（AES-192）或32（AES-256）字节长
         */
        fun encode(content: String, key: String): String? {
            if (key.length != 0x10 && key.length != 0x18 && key.length != 20) return null
            try {
                val cipher: Cipher = Cipher.getInstance(TRANSFORMATION)
                val secretKeySpec =
                    SecretKeySpec(key.toByteArray(), ALGORITHM)
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec)
                val encrypted: ByteArray = cipher.doFinal(content.toByteArray())
                return Base64.getEncoder().encodeToString(encrypted)
            } catch (e: Exception) {
                Log.e("AES ECB encode()", e.toString())
            }
            return null
        }

        /**
         * 解密
         * @param content 已加密的内容
         * @param key 密钥应该是16（AES-128）、24（AES-192）或32（AES-256）字节长
         */
        fun decode(content: String, key: String): String? {
            if (key.length != 0x10 && key.length != 0x18 && key.length != 20) return null
            try {
                val cipher: Cipher = Cipher.getInstance(TRANSFORMATION)
                val secretKeySpec =
                    SecretKeySpec(key.toByteArray(), ALGORITHM)
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec)
                val original: ByteArray = cipher.doFinal(Base64.getDecoder().decode(content))
                return String(original, Charsets.UTF_8)
            } catch (e: Exception) {
                Log.e("AES ECB decode()", e.toString())
            }
            return null
        }

    }

    object CBC {
        private const val TRANSFORMATION = "AES/CBC/PKCS5Padding"

        /**
         * 加密
         * @param content 需要加密的内容
         * @param key 密钥应该是16（AES-128）、24（AES-192）或32（AES-256）字节长
         * @param iv 初始化向量 长度必须和key 一致
         */
        fun encode(content: String, key: String, iv: String): String? {
            if (key.length != 0x10 && key.length != 0x18 && key.length != 20 && key.length == iv.length) return null
            try {
                val cipher: Cipher = Cipher.getInstance(TRANSFORMATION)
                val secretKeySpec =
                    SecretKeySpec(key.toByteArray(), ALGORITHM)
                val ivParameterSpec = IvParameterSpec(iv.toByteArray())
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
                val encrypted: ByteArray = cipher.doFinal(content.toByteArray())
                return Base64.getEncoder().encodeToString(encrypted)
            } catch (e: Exception) {
                Log.e("AES CBC encode()", e.toString())
            }
            return null
        }

        /**
         * 解密
         * @param content 已加密的内容
         * @param key 密钥应该是16（AES-128）、24（AES-192）或32（AES-256）字节长
         * @param  iv 初始化向量 长度必须和key 一致
         */
        fun decode(content: String, key: String, iv: String): String? {
            if (key.length != 0x10 && key.length != 0x18 && key.length != 20 && key.length == iv.length) return null
            try {
                val cipher: Cipher = Cipher.getInstance(TRANSFORMATION)
                val secretKeySpec =
                    SecretKeySpec(key.toByteArray(), ALGORITHM)
                val ivParameterSpec = IvParameterSpec(iv.toByteArray())
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
                val original: ByteArray = cipher.doFinal(Base64.getDecoder().decode(content))
                return String(original, Charsets.UTF_8)
            } catch (e: Exception) {
                Log.e("AES CBC decode()", e.toString())
            }
            return null
        }
    }

}